#include <dt-bindings/gpio/gpio.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/err.h>



#include <linux/workqueue.h>  //添加对应头文件


//用新的gpio接口
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>


#include <linux/device.h>

struct pinctrl* gpio_pinctrl;
struct pinctrl_state* led_state1;
struct pinctrl_state* spi_state2;

/***
 自己实现的代码：测试过

   
// 1.设备树描述
	led_ctrl15:led_ctrl15_gpio4 {
		    status = "okay";
            compatible = "rk3568_led_ctrl15";
            redgpio-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>;
           // pinctrl-names = "default";
		    pinctrl-names = "mypinctrl1","mypinctrl2";
            pinctrl-0 = <&led_ctrl_gpio1>;         //复用gpio
			pinctrl-1 = <&led_ctrl_spi_clk2>;      //复用spi3的clk
    };

	&pinctrl{
			led_ctrl15_group1{
			led_ctrl_gpio1:led_ctrl_gpio1-pins{
                 rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
			};
	};
	led_ctrl15_group2{
			led_ctrl_spi_clk2:led_ctrl_spi_clk2-pins{
			
//看数据手册
// gpio4c2_sel
// 3'h0: GPIO4_C2
// 3'h1: PWM14_M1
// 3'h2: SPI3_CLKM1
// 3'h3: CAN1_RXM1
// 3'h4: PCIE30X2_CLKREQNM2
// 3'h5: I2S3_MCLKM1     找不到宏，直接写0,1算了
				
				rockchip,pins = <4 RK_PC2 2 &pcfg_pull_up>;  
			}; 
	};
	}

// 2.代码编写，如下面

//3 .测试
  *  实验效果：

 cat /sys/kernel/debug/pinctrl/pinctrl/pinmux-pins
  * echo 1 > selectmux
 pin 146 (gpio4-18): led_ctrl15_gpio4 (GPIO UNCLAIMED) function led_ctrl15_group1 group led_ctrl_gpio1-pins
 设置为gpio

 echo 2 > selectmux
 pin 146 (gpio4-18): led_ctrl15_gpio4 (GPIO UNCLAIMED) function led_ctrl15_group2 group led_ctrl_spi_clk2-pins

 * 
 * 
 */

	// ssize_t (*show)(struct device *dev, struct device_attribute *attr,
	// 		char *buf);
ssize_t selectmux_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){
       int ret;
// buf应用层传递进来，转化为unsigned long
	    unsigned long select; 
		select =  simple_strtoul(buf,NULL,10);
		if( select == 1 ){
           ret = pinctrl_select_state(gpio_pinctrl,led_state1);
           if(ret < 0){
	         printk("pinctrl_select_state led_state1  is error \n");
	         return -2;
	      }
    	} else if(select ==2){
            ret = pinctrl_select_state(gpio_pinctrl,spi_state2);
           if(ret < 0){
	         printk("pinctrl_select_state spi_state2  is error \n");
	         return -3;
	      }
    	 }
	 return count; 
};

DEVICE_ATTR_WO(selectmux);





// 查找复用状态 
int pinctrl_get_and_lookstate(struct device *dev){

    gpio_pinctrl= pinctrl_get(dev);
	if(IS_ERR(gpio_pinctrl)){
		printk("gpio_pinctrl is error\n");
		return -1;
	}


	//获取pinctrl状态
    led_state1= pinctrl_lookup_state(gpio_pinctrl,"mypinctrl1");
	if(IS_ERR(led_state1)){
		printk("led_state1 is error\n");
		return -2;
	}


	spi_state2= pinctrl_lookup_state(gpio_pinctrl,"mypinctrl2");
	if(IS_ERR(spi_state2)){
		printk("spi_state2 is error\n");
		return -3;
	}
     return 0; 

};




// 第一章：驱动开发
static int led_ctrl_probe(struct platform_device *pdev) //compatible的属性和dts的compatible一致，就会调用probe函数
{
    printk("rk3568_gpiod_apil15--->led_ctrl_probe");

//查找复用状态 
	pinctrl_get_and_lookstate(&pdev->dev);
// 在平台总线下创建属性文件
	device_create_file(&pdev->dev,&dev_attr_selectmux);

	return 0;
}


static int led_ctrl_remove(struct platform_device *pdv)
{
	return 0;
}


static struct of_device_id led_ctrl_match_table [] = {
	{.compatible = "rk3568_led_ctrl15",}, //这里应该要跟dts的.compatible保持一致，我这里视频课程中没有写成一样，
        {},						//但他有个模糊匹配的功能，就是匹配相近的字段, 为了防止出错，大家最好写成跟dts一样的字段
	};

static struct platform_driver led_ctrl_driver = {
        .driver         = {
                .name = "rk3568_led_ctrl15",
		.owner = THIS_MODULE, 
                .of_match_table = led_ctrl_match_table,
        },
        .probe          = led_ctrl_probe,
	.remove = led_ctrl_remove,
};

static int led_ctrl_init(void)
{
	printk("%s(), __%d__\n", __func__, __LINE__);

	platform_driver_register(&led_ctrl_driver); //注册platform平台总线驱动
	return 0;
};

static void led_ctrl_exit(void)
{
	printk("%s(), __%d__\n", __func__, __LINE__);
	
	platform_driver_unregister(&led_ctrl_driver); //注销驱动
};


module_init(led_ctrl_init); //模块加载函数, linux启动， insmod 驱动的时候 
module_exit(led_ctrl_exit); //模块卸载函数

MODULE_AUTHOR("caigong, 214241976@qq.com");   // 邮箱
MODULE_DESCRIPTION("Control Led Driver");    //作者
MODULE_LICENSE("GPL");       //驱动遵守的开源协议GPL
